#include <bits/stdc++.h>

#define in read()
#define fi first
#define se second
#define pb push_back
#define rep(i, x, y) for(int i = (x); i <= (y); i++) 
#define per(i, x, y) for(int i = (x); i >= (y); i--)

using namespace std;

using ll = long long;
using db = double;
using pii = pair < int , int >;
using vec = vector < int >;
using veg = vector < pii >;

int read() {
	int x = 0; bool f = 0; char ch = getchar(); while(!isdigit(ch)) f |= ch == '-', ch = getchar(); 
	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar(); return f ? -x : x;
}

const int N = 1e5 + 10;

int fa[N], siz[N], dep[N], top[N], son[N], dfn[N], tim, n, Q;
int t[N << 2], a[N << 2], b[N << 2], ans[N << 2];
vec G[N];

int gf(int x) { return x == fa[x] ? x : fa[x] = gf(fa[x]); }

void dfs(int x, int p) {
	fa[x] = p; siz[x] = 1; dep[x] = dep[p] + 1; 
	for(auto y : G[x]) if(y ^ p) dfs(y, x), siz[x] += siz[y], son[x] = siz[y] > siz[son[x]] ? y : son[x]; 
}

void dfs1(int x, int anc) {
	top[x] = anc; dfn[x] = ++tim; if(son[x]) dfs1(son[x], anc);
	for(auto y : G[x]) if(y ^ fa[x] && y ^ son[x]) dfs1(y, y); 
}

namespace seg {
	int ans[N << 2]; bool tg[N << 2];
	inline void pt(int o) { tg[o] = 1, ans[o] = 0; }
	inline void pd(int o) { if(tg[o]) pt(o << 1), pt(o << 1 | 1), tg[o] = 0; }
	inline void pu(int o) { ans[o] = ans[o << 1] + ans[o << 1 | 1]; }
	void build(int o = 1, int l = 1, int r = n) {
		ans[o] = r - l + 1; if(l == r) return; int mid = l + r >> 1;
		build(o << 1, l, mid); build(o << 1 | 1, mid + 1, r); 
	}
	void upd(int xl, int xr, int o = 1, int l = 1, int r = n) {
		if(xl == l && xr == r) return pt(o); int mid = l + r >> 1; pd(o);
		if(xr <= mid) upd(xl, xr, o << 1, l, mid); else if(xl > mid) upd(xl, xr, o << 1 | 1, mid + 1, r);
		else upd(xl, mid, o << 1, l, mid), upd(mid + 1, xr, o << 1 | 1, mid + 1, r); pu(o);
	}
	int query(int xl, int xr, int o = 1, int l = 1, int r = n) {
		if(xl == l && xr == r) return ans[o]; int mid = l + r >> 1; pd(o);
		if(xr <= mid) return query(xl, xr, o << 1, l, mid); else if(xl > mid) return query(xl, xr, o << 1 | 1, mid + 1, r);
		else return query(xl, mid, o << 1, l, mid) + query(mid + 1, xr, o << 1 | 1, mid + 1, r); 
	}
	void modify(int x, int y) {
		while(top[x] ^ top[y]) {
			if(dep[top[x]] < dep[top[y]]) swap(x, y);
		    upd(dfn[top[x]], dfn[x]); x = fa[top[x]];
		} if(dfn[x] > dfn[y]) swap(x, y); if(dfn[x] ^ dfn[y]) upd(dfn[x] + 1, dfn[y]);
	}
	int qtree(int x, int y) {
		int res = 0; 
		while(top[x] ^ top[y]) {
			if(dep[top[x]] < dep[top[y]]) swap(x, y);
		    res += query(dfn[top[x]], dfn[x]); x = fa[top[x]];
		} if(dfn[x] > dfn[y]) swap(x, y); if(dfn[x] ^ dfn[y]) res += query(dfn[x] + 1, dfn[y]);
		return res;
	}
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
#endif
	n = in, Q = in;
	rep(i, 1, n) fa[i] = i, siz[i] = 1; 
	rep(i, 1, Q) {
		t[i] = in, a[i] = in, b[i] = in;
		if(t[i] == 2 && gf(a[i]) != gf(b[i])) ans[i] = -1;
		if(t[i] == 1 && gf(a[i]) != gf(b[i])) {
			int x = a[i], y = b[i], fx = gf(x), fy = gf(y);
			if(siz[fx] > siz[fy]) swap(fx, fy);
			G[x].pb(y); G[y].pb(x); siz[fy] += siz[fx]; fa[fx] = fy; t[i] = 0; 
		}
	}
	rep(i, 1, n) if(!dep[i]) dfs(i, 0), dfs1(i, i); seg :: build();
	rep(i, 1, Q) {
		if(t[i] == 1) seg :: modify(a[i], b[i]);
		if(t[i] == 2 && ans[i] != -1) ans[i] = seg :: qtree(a[i], b[i]);
		if(t[i] == 2) printf("%d\n", ans[i]);
	}
	return 0;
}
